/**
 * @file CMSignalAction.cpp
 * @author jmdvirus
 * @date 2021-06-16 18:01:52
 */

#include <execinfo.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ucontext.h>
#include <vector>

#include "CMSignalAction.h"

static signal_action *  s_sigaction = NULL;
static std::vector<int> s_ignore_signals;
static std::vector<int> s_do_signals = {SIGSEGV, SIGABRT, SIGBUS};

static void signal_ret(int sig)
{
    sigignore(sig);
    printf("[%s:%d] signal %d\n", __func__, __LINE__, sig);
    bool find = false;
    for (auto &i : s_do_signals)
    {
        if (i == sig)
        {
            find = true;
            break;
        }
    }
    if (!find && s_sigaction)
    {
        s_sigaction(sig);
        return;
    }
    CMBacktraceSelf backtraceSelf;
    int             s = 20;
    void *          array[s];
    s = backtrace(array, s);
    backtraceSelf.print_backtrace_normal(array, s);
    exit(0);
}

void ignore_signal(int sig) { s_ignore_signals.push_back(sig); }

int init_signal(signal_action *callback)
{
    s_sigaction = callback;
    struct sigaction sa;
    sigemptyset(&sa.sa_mask);
    memset(&sa, 0, sizeof(sa));
    sa.sa_handler = signal_ret;
    sa.sa_flags   = 0;

    bool find = false;
    for (auto &j : s_ignore_signals)
    {
        if (j == SIGPIPE)
        {
            find = true;
            break;
        }
    }
    if (!find)
    {
        s_do_signals.push_back(SIGPIPE);
    }
    for (auto &i : s_do_signals)
    {
        sigaction(i, &sa, NULL);
    }
    return 0;
}
